package cn.kgc.vue.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.kgc.vue.common.ResponseResult;
import cn.kgc.vue.common.ResponseStatus;
import cn.kgc.vue.entity.*;
import cn.kgc.vue.form.UserInforForm;
import cn.kgc.vue.form.UserLoginForm;
import cn.kgc.vue.form.UserLsitForm;
import cn.kgc.vue.mapper.*;
import cn.kgc.vue.service.UserService;
import cn.kgc.vue.utils.JWTUtil;
import cn.kgc.vue.utils.SaltUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RolePersMapper rolePersMapper;
    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public ResponseResult login(UserLoginForm userLoginForm) {
        ResponseResult responseResult = new ResponseResult();
        // 1.判定验证码
        String code = userLoginForm.getCode();
        String imguuid = userLoginForm.getImguuid();
        // 根据uuid 获取redis中缓存的验证码
        String captcha = stringRedisTemplate.opsForValue().get(imguuid);
        //比较  captcha 时效性   code
        if (StringUtils.isEmpty(captcha)) {
            responseResult.fail(ResponseStatus.CODE_EXPIRE);
            return responseResult;
        }
        if (!StringUtils.equals(code, captcha)) {
            responseResult.fail(ResponseStatus.CODE_ERROR);
            return responseResult;
        }
        // 2.验证码判定通过   封装token 实现验证
        String username = userLoginForm.getUsername();
        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
        lambda.eq(User::getUsername, username);
        User user = userMapper.selectOne(lambda);
        // 判定用户是否存在
        if (ObjectUtil.isEmpty(user)) {
            throw new UnknownAccountException("用户名不存在");
        }

        // 判定密码是否正确
        String salt = user.getSalt();
        String md5Pwd = new Md5Hash(userLoginForm.getPassword(), salt, 1024).toHex();
        String password = user.getPassword();
        if (!StringUtils.equals(md5Pwd, password)) {
            throw new IncorrectCredentialsException("密码错误");
        }

        //判定用户状态  是否可用  state  1 正常    0 禁用
        Integer state = user.getState();
        if (state == 0) {
            throw new LockedAccountException("账户被禁用");
        }
        // 3.登录成功  生成token  返回前端
        // token的载荷
        HashMap<String, Object> claims = new HashMap<>();
        claims.put("username", user.getUsername());
        claims.put("userId", user.getId());
        String token = JWTUtil.createToken(claims);
        // 需要返回到前端的数据
        HashMap<String, Object> data = new HashMap<>();
        data.put("token", token);
        data.put("nickName", user.getNickName());
        responseResult.success(ResponseStatus.LOGIN_SUCCESS, data);
        return responseResult;
    }


    @Override
    public ResponseResult userList(UserLsitForm userLsitForm) {

        Page<User> objectPage = new Page<>(userLsitForm.getPage(), userLsitForm.getLimit());
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.isNotEmpty(userLsitForm.getUsername()),User::getUsername,userLsitForm.getUsername())
                .eq(!Objects.isNull(userLsitForm.getState()),User::getState,userLsitForm.getState()).orderByDesc(User::getId);
        Page<User> userPage = userMapper.selectPage(objectPage, wrapper);
        long total = userPage.getTotal();
        List<User> records = userPage.getRecords();
        //先获取部门
        for (User user : records) {
            Integer deptId = user.getDeptId();
            //然后获取deptName
            Dept dept = deptMapper.selectById(deptId);
            if(dept!=null){
                user.setDeptName(dept.getDeptName());
            }
        }
        //然后获取角色信息
        for (User user : records) {
            LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserRole::getUserId,user.getId());
            List<UserRole> userRoles = userRoleMapper.selectList(queryWrapper);
            if(!CollectionUtils.isEmpty(userRoles)){
                List<Integer> roleId = userRoles.stream().map(s -> s.getRoleId()).collect(Collectors.toList());
                List<Role> roles = roleMapper.selectBatchIds(roleId);
                user.setRoles(roles);
            }
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("user",records);
        map.put("total",total);
        ResponseResult responseResult = new ResponseResult();
        responseResult.success(ResponseStatus.SUCCESS,map);
        return responseResult;
    }
    @Override
    @Transactional
    public ResponseResult updateuser(UserInforForm userInforForm) {
        ResponseResult responseResult = new ResponseResult();
        //更新用户信息
        User user = new User();
        BeanUtils.copyProperties(userInforForm,user);
        userMapper.updateById(user);
        //将user_role的关系表删除
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(UserRole::getUserId,user.getId());
        userRoleMapper.delete(wrapper);
        //然后再进行添加
        Integer[] roleId = userInforForm.getRoleId();
        for (Integer integer : roleId) {
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId(integer);
            userRoleMapper.insert(userRole);
        }
        responseResult.success();
        return responseResult;
    }
    @Override
    @Transactional
    public ResponseResult addUser(UserInforForm userInforForm) {
        ResponseResult responseResult = new ResponseResult();
        User user = new User();
        BeanUtils.copyProperties(userInforForm,user);
        //添加用户信息
        String username = user.getUsername();
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername,username);
        User one = userMapper.selectOne(wrapper);
        if(!Objects.isNull(one)){
            responseResult.fail(ResponseStatus.KNOWN_ACCOUNT);
            return responseResult;
        }
        String salt = SaltUtil.getSalt(4);
        user.setSalt(salt);
        String s = new Md5Hash("8888", salt, 1024).toString();
        user.setPassword(s);
        //添加用户
        userMapper.insert(user);
        //然后再进行添加用户角色表
        Integer[] roleId = userInforForm.getRoleId();
        for (Integer integer : roleId) {
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId(integer);
            userRoleMapper.insert(userRole);
        }
        responseResult.success(ResponseStatus.ADD_SUCCESS);
        return responseResult;
    }

    @Override
    @Transactional
    public ResponseResult delete(List<Integer> ids) {
        ResponseResult responseResult = new ResponseResult();
        //批量删除用户信息
        userMapper.deleteBatchIds(ids);
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        for (Integer id : ids) {
            wrapper.eq(UserRole::getUserId,id);
            userRoleMapper.delete(wrapper);
        }
        responseResult.success(ResponseStatus.DELETE_SUCCESS);
        return responseResult;
    }

    @Override
    public ResponseResult getmenulist(HttpServletRequest request) {
        ResponseResult responseResult = new ResponseResult();
        String token = request.getHeader("token");
        //获取用户的id
        Integer userId = (Integer) JWTUtil.getClaim(token).get("userId");
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId,userId);
        //获取角色id
        List<Integer> roleList = userRoleMapper.selectList(wrapper).stream().map(s -> s.getRoleId()).collect(Collectors.toList());
        //获取pid
        LambdaQueryWrapper<RolePers> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.in(RolePers::getRoleId,roleList);
        Set<Integer> collect = rolePersMapper.selectList(wrapper1).stream().map(s -> s.getPerId()).collect(Collectors.toSet());
        if(ObjectUtils.isNotEmpty(collect)){
            //查找菜单名字
            LambdaQueryWrapper<Permission> wrapper2 = new LambdaQueryWrapper<>();
            wrapper2.in(Permission::getId,collect).ne(Permission::getIsMenu,2);
            List<Permission> list = permissionMapper.selectList(wrapper2);
            responseResult.success(ResponseStatus.SUCCESS,list);
            return responseResult;
        }
        responseResult.success(ResponseStatus.SUCCESS,new ArrayList<>());
        return responseResult;
    }
}




